package com.example.threadmodel;

import com.example.threadmodel.model.NamedPoolThreadFactory;
import com.example.threadmodel.model.Student;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Queue;
import java.util.concurrent.*;

/**
 * 功能：测试直接在主线程从队列取任务执行简单业务 和 放单线程执行，同时有 CountDownLatch
 * 结论：从队列取任务耗时不大，7/100_000 ms,  取任务，CountDownLatch 这些都是有耗时的,反而占耗时大头
 */
@Slf4j
@SpringBootTest
public class Demo2_TestPoolTaskFromQueueVsSingleThreadPoolAndCountDownLatch {

    /*
     功能：测试往队列中扔，然后从队列中取任务执行的消耗(10W次)
     2025-09-04 00:09:42 [WARN ] [main] c.e.t.Demo2_OnePlayerWithSimpleTask.testQueueCostTime(Demo2_OnePlayerWithSimpleTask.java:55) - 往队列放数据消耗:6
    2025-09-04 00:09:42 [WARN ] [main] c.e.t.Demo2_OnePlayerWithSimpleTask.testQueueCostTime(Demo2_OnePlayerWithSimpleTask.java:57) - size:100000
    2025-09-04 00:09:42 [WARN ] [main] c.e.t.Demo2_OnePlayerWithSimpleTask.testQueueCostTime(Demo2_OnePlayerWithSimpleTask.java:69) - Queue模式不断从队列取数据并执行所有的任务消耗:7
     */
    @Test
    public void testQueueCostTime() throws Exception {
        int studentNum = 1;
        int execCount = 100_000;

        ConcurrentHashMap<String, Student> studentMap = new ConcurrentHashMap<>();
        for (int i = 0; i < studentNum; i++) {
            studentMap.put(i + "", new Student(i + "", 0));
        }

        String queueId = "0";

        // 非阻塞
        Queue<Callable> queue = new ConcurrentLinkedQueue<>();

        Student student = studentMap.get(queueId);

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < execCount; i++) {
            queue.offer(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    student.doSimpleLogic(student.getCoinCount() + 1);
                    return 0;
                }
            });
        }

        log.warn("往队列放数据消耗:{}", System.currentTimeMillis() - startTime);

        log.warn("size:{}", queue.size());

        long startTime2 = System.currentTimeMillis();
        while (!queue.isEmpty()) {
            Callable<Integer> action = queue.poll();
            try {
                action.call();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        log.warn("Queue模式不断从队列取数据并执行所有的任务消耗:{}", System.currentTimeMillis() - startTime2);

        TimeUnit.SECONDS.sleep(Long.MAX_VALUE);
    }


    /*
    功能：在绑定的线程执行(10W)
    2025-08-31 20:49:18 [WARN ] [main] c.e.t.Demo1_QueueCostTimeTests.testSingleThread(Demo1_QueueCostTimeTests.java:98) - 直接在绑定的线程执行完任务消耗:452
     */
    @Test
    public void testSingleThread() throws Exception {
        int studentNum = 1;
        int execCount = 100_000;

        CountDownLatch countDownLatch = new CountDownLatch(studentNum * execCount);

        String queueId = "0";
        Student student = new Student(queueId, 0);

        ExecutorService singleLogicThread = Executors.newSingleThreadExecutor(new NamedPoolThreadFactory("single_logic_thread"));

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < execCount; i++) {
            singleLogicThread.submit(() -> {
                student.doSimpleLogic(student.getCoinCount() + 1);
                countDownLatch.countDown();
            });
        }

        countDownLatch.await();

        log.warn("直接在绑定的线程执行完任务消耗:{}", System.currentTimeMillis() - startTime);

        singleLogicThread.shutdown();

        TimeUnit.SECONDS.sleep(Long.MAX_VALUE);
    }
}
